#ifndef WORKFLOW_H_INCLUDED
#define WORKFLOW_H_INCLUDED

#include <time.h>

#include "Base/lib/lib.queue.h"
#include "Base/lib/lib.hashtable.h"


typedef struct taskchain{

    /**<
        nextLen indicates how many following tasks there are*/
    int nextLen;
    /**<
        pq is the queue where we store the following taksChains*/
    queue *pq;

    /**<
        p_data void *
        the structure which will be handled by task plugins.
        Task plugin needs to malloc p_data in initTask() and free it in freeTask() after the task is done or failed.
     */
    void *p_data;

    /**<
     1 means Required If the task fails, the workflow will fail immediately
     0 means optional If the task fails, the workflow will skip it and execute next tasks.
     */
    int option;

    /**<
        hkey (short for hashkey) is used to indicate which plugin will handle the p_data
         It can be a process handling call back function or a file_arriving call back function
    */
    char * hkey;


    /**<
        1 means the task is done sucessfully
        0 means the task is failed*/
    int revCode;

    /**<
        errMessage stores the error message if the task goes wrong.
        task plugin needs set it up in execTask
        */
    char *errMessage;

    /**<
        waitCount indicates
        the count of how many conditions the task should meet in order to get triggered. */
    int waitCount;

#if defined OS_LINUX
    char * shell;
    char ** sys_variables;
#endif

    char *errFile;
    //char *inFile;
    char *outFile;

    char * run_uname;

}taskchain;


/**<  We will have a head node and a tail node with non-process.
      The head node's lenght is >0; head_node's p_pro is NULL.
      The tail node's length is 0; tail-node's p_pro is NULL

      if we have a workflow like below:
                   --p-->    c
               a  ------>    d
 headnode         ---q-->    e
                                            tailnode (All terminate task will be pointed to tail node
               b  ----->
               c  ----->
   */

typedef struct wasWorkFlow{

    /**< Workflow id */
    long long *fid;

    /**< Workflow name */
    char *wf_name;

    /**< Description of the work flow
     */
    char *comments;

    taskchain *p_tc;

    /**< flow start_time */
    time_t s_time;

    /**< flow ends time */
    time_t f_time;

    /**<
        waitCount indicates
        the count of how many conditions the workflow should meet in order to get triggered.
        This always happens when it is included as a sub work flow.
        0 means it is not a subflow (but a standalone flow)
        */
    int waitCount;

    /**<
     0 One of the required task failed
     1 Completely sucess
     2 Some of the optional tasks failed. Required tasks all succeed
    */
    int status;
}wasWorkFlow;


typedef struct taskchainPlugin{
    /**< hash key for finding the plugin in the hash buket */
//    char *hkey;

    char *pluginName;
    void *handle;

//    int (*checkTaskStatus)(void *p_data);
//    int (*execTask)(void *p_data,char **errMessage);
//
//    int (*initTask)(void **p_data);
//
//    int (*freeTask)(void **p_data);
    //char *plugin;
}taskchainPlugin;

typedef struct wasprocess{
    char *pname;
    char *path;
//    char *stdin;
//    char *stdout;
//    char *stderr;
    char *pid;
    //char *run_user;
    //time_t start_time;
    //time_t end_time;

    //int wait_condition;
    int * status;   /**/
}wasprocess;



/******************************
BEGIN Functions
that a taskchainPlugin needs to implement
********************************/

/**< Return values for checkTaskStatus(void *p_data) */

#define PENDING     0
#define RUNNING     1
#define SUSPENDED   2
#define KILLED      3
#define DONE        4

/** \brief
 *
 * \param p_data void*
    This is the structure that a plugin defines.
    The plugin will malloc this structure in
 * \return int
    PENDING      means the task is not triggered yet
    RUNNING      means the task has been already started and running
    SUSPENED
    KILLED
    DONE
 *
 */
int checkTaskStatus(void *p_data);

#define SUCCESS 1
#define FAILURE 0

/** \brief
 *
 * \param p_data void*
	This is the p_data that the plugin defines.
   \param errMessage char **
    If the function does not execute sucessfully, you have to malloc a variable (char *), and point
    *errMessage to it.
	char *temp=(char *) malloc(sizeof(char)*LEN);
	*errMessage=temp;
 * \return int
	Done
	Failure
 *
 */
int execTask(void *p_data,char **errMessage);

int initTask(void **p_data);

int freeTask(void **p_data);


/******************************
END Functions
that a taskchainPlugin needs to implement
********************************/

BOOL loadWFlowPlugin_EX(const char* const pluginPath);
hTab *getWorkFlowPlugin();
BOOL freeWorkFlowPlugin(hTab *p_tab);

#endif // WORKFLOW_H_INCLUDED
